package com.test.uimremote.sim;

import android.content.Context;
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;

import com.qualcomm.uimremoteclient.IUimRemoteClientService;
import com.test.uimremote.MainActivity;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 接收jni传来的数据并通过aidl转发给高通控制端app
 *
 * @author zhupeizhen
 * 2020/12/4
 */
public class ServerProxy {

    private static final String PROXY_HOST = "127.0.0.1";
    private static final int PROXY_PORT = 8848;

    private final Context mContext;

    private IUimRemoteClientService mService = null;

    private int mCount = 0;

    private static final ExecutorService socketProcessor = Executors.newFixedThreadPool(8);
    private static ServerSocket mServerSocket;
    private static int mPort;

    BufferedInputStream mClientInputStream;
    BufferedOutputStream mClientOutputStream;
    private Toast mToast;

    Handler handler = new Handler();

    public ServerProxy(Context context) {
        mContext = context;
        initProxy();
    }

    public static String byte2hex(byte[] arr) {
        StringBuilder sb = new StringBuilder();
        String stmp = "";
        for (int n = 0; n < arr.length; n++) {
            stmp = (java.lang.Integer.toHexString(arr[n] & 0XFF));
            if (stmp.length() == 1) {
                sb.append("0").append(stmp).append(" ");
            } else {
                sb.append(stmp).append(" ");
            }
        }
        return sb.toString().toUpperCase();
    }

    private void initProxy() {
        if (mServerSocket == null) {
            try {
                InetAddress inetAddress = InetAddress.getByName(PROXY_HOST);
                mServerSocket = new ServerSocket(PROXY_PORT, 8, inetAddress);
                mPort = mServerSocket.getLocalPort();
                Log.i("proxyTest", "new serverSocket inetAddress=" + inetAddress + ",mPort=" + mPort);
                new Thread() {
                    @Override
                    public void run() {
                        while (!Thread.currentThread().isInterrupted()) {
                            try {
                                final Socket socket = mServerSocket.accept();
                                Log.i("proxyTest", "Accept new socket " + socket);

                                new Thread(() -> {
                                    try {
                                        mClientInputStream = new BufferedInputStream(socket.getInputStream());
                                        mClientOutputStream = new BufferedOutputStream(socket.getOutputStream());
                                        byte[] buffer = new byte[8 * 10 * 1024];

                                        while (!Thread.currentThread().isInterrupted()) {

//                                                StringBuffer stringBuffer = new StringBuffer();
                                            int read;
                                            int count = 0;

                                            byte[] resultByte = null;

                                            while ((read = mClientInputStream.read(buffer, 0, buffer.length)) != -1) {
//                                                    stringBuffer.append(buffer);

//                                                Log.i("proxyTest", "收到jni数据,buffer.length=" + read + ",buffer=" + Arrays.toString(buffer));

                                                // 获取到jni客户端传来的消息
                                                /*mServerOutputStream.write(buffer, 0, read);
                                                mServerOutputStream.flush();*/

                                                byte[] bytesTemp = new byte[read];
                                                System.arraycopy(buffer,0,bytesTemp,0,read);
//                                                resultByte = concat(resultByte, bytesTemp);

                                                Log.i("proxyTest", "收到jni数据,bytesTemp.length=" + bytesTemp.length + ",bytesTemp=" + byte2hex(bytesTemp));
//                                                Log.i("proxyTest", "收到jni数据,resultByte.length="
//                                                        + resultByte.length + ",resultByte=" + Arrays.toString(resultByte));

                                                if (mService != null) {
                                                    if (bytesTemp.length > 0 && bytesTemp[0] == 0x3B) {
                                                        int i = mService.uimRemoteEvent(MainActivity.UimSlot.UIM_REMOTE_SLOT0, MainActivity.UimRemoteEvent.UIM_REMOTE_CONNECTION_AVAILABLE, bytesTemp,
                                                                MainActivity.UimRemoteErrcode.UIM_REMOTE_CARD_ERROR_UNKNOWN, false, 0, false, 0,
                                                                true, 7, true, 1, false, 0);
                                                        mCount++;
                                                        Log.i("proxyTest", "写入高通uimRemoteEvent=" + i);
                                                    } else {
                                                        int i = mService.uimRemoteApdu(MainActivity.UimSlot.UIM_REMOTE_SLOT0, 0, bytesTemp);
                                                        Log.i("proxyTest", "写入高通uimRemoteApdu=" + (i == 0 ? "成功" : "失败"));
                                                    }

                                                } else {
                                                    handler.post(new Runnable() {
                                                        @Override
                                                        public void run() {
                                                            if (mToast != null) {
                                                                mToast.cancel();
                                                            }
                                                            mToast = Toast.makeText(mContext, "收到jni数据，高通端连接失败", Toast.LENGTH_SHORT);
                                                            mToast.show();
                                                        }
                                                    });
                                                    Log.e("proxyTest", "收到jni数据，高通端连接失败");
                                                }

                                                count += read;
//                                                Log.e("proxyTest", "client.inputStream=" + ", count=" + read);
                                            }

                                        }

                                    } catch (IOException | RemoteException e) {
                                        Log.e("proxyTest", "client.exception=" + e);

//                                            if (mServerMsgThread != null) {
//                                                mServerMsgThread.interrupt();
//                                                try {
//                                                    socket.close();
//                                                    mServerMsgThread = new Thread(new Runnable() {
//                                                        @Override
//                                                        public void run() {
//                                                            processServerMsg(currentURL);
//                                                        }
//                                                    });
//                                                    mServerMsgThread.start();
//                                                } catch (IOException ex) {
//                                                    ex.printStackTrace();
//                                                }
//                                            }

                                        e.printStackTrace();
                                    }
                                }).start();

//                                socketProcessor.submit();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                            //                LOG.debug("Accept new socket " + socket);
                        }
                    }
                }.start();

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void writeToJni(byte[] buffer) {
        if (mClientOutputStream != null) {
            try {
                mClientOutputStream.write(buffer, 0, buffer.length);
                mClientOutputStream.flush();
                Log.i("proxyTest", "高通数据写入jni完成 length=" + buffer.length);
            } catch (IOException e) {
                e.printStackTrace();
                Log.e("proxyTest", "写入失败 e=" + e);
            }
        } else {
            Log.e("proxyTest", "jni未连接");
        }
    }

    public IUimRemoteClientService getAidlService() {
        return mService;
    }

    public void setAidlService(IUimRemoteClientService mService) {
        this.mService = mService;
    }

    private byte[] concat(byte[] a, byte[] b) {
        if (a == null) {
            return b;
        }
        byte[] c = new byte[a.length + b.length];
        System.arraycopy(a,0,c,0,a.length);
        System.arraycopy(b,0,c,a.length, b.length);
        return c;
    }

}
